{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Gradient Matching Attack on a TF Classifier"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook, we will learn how to use ART to run a clean-label gradient matching poisoning attack on a neural network trained with Tensorflow. We will be training our data on a subset of the CIFAR-10 dataset. The methods described are derived from [this paper](https://arxiv.org/abs/2009.02276) by Geiping, et. al. 2020."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train a model to attack\n",
    "\n",
    "In this example, we use a RESNET50 model on the CIFAR dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "313/313 [==============================] - 3s 8ms/step - loss: 0.4160 - accuracy: 0.9146\n",
      "Model and data preparation done.\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import os, sys\n",
    "\n",
    "module_path = os.path.abspath(os.path.join('..'))\n",
    "if module_path not in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "module_path = os.path.abspath(os.path.join('.'))\n",
    "if module_path not in sys.path:\n",
    "    sys.path.append(module_path)\n",
    "\n",
    "from art.estimators.classification import TensorFlowV2Classifier\n",
    "from art.utils import load_cifar10\n",
    "\n",
    "(x_train, y_train), (x_test, y_test), min_, max_ = load_cifar10()\n",
    "\n",
    "mean = np.mean(x_train,axis=(0,1,2,3))\n",
    "std = np.std(x_train,axis=(0,1,2,3))\n",
    "x_train = (x_train-mean)/(std+1e-7)\n",
    "x_test = (x_test-mean)/(std+1e-7)\n",
    "\n",
    "min_ = (min_-mean)/(std+1e-7)\n",
    "max_ = (max_-mean)/(std+1e-7)\n",
    "\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense, Flatten\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "from tqdm.keras import TqdmCallback\n",
    "\n",
    "tf.get_logger().setLevel('ERROR')\n",
    "\n",
    "# Tweaked the model from https://github.com/calmisential/TensorFlow2.0_ResNet\n",
    "# MIT License\n",
    "def basic_block(x, filter_num, stride=1):\n",
    "    conv1 = tf.keras.layers.Conv2D(filters=filter_num,\n",
    "                                        kernel_size=(3, 3),\n",
    "                                        strides=stride,\n",
    "                                        padding=\"same\")\n",
    "    bn1 = tf.keras.layers.BatchNormalization()\n",
    "    conv2 = tf.keras.layers.Conv2D(filters=filter_num,\n",
    "                                        kernel_size=(3, 3),\n",
    "                                        strides=1,\n",
    "                                        padding=\"same\")\n",
    "    bn2 = tf.keras.layers.BatchNormalization()\n",
    "    if stride != 1:\n",
    "        downsample = tf.keras.Sequential()\n",
    "        downsample.add(tf.keras.layers.Conv2D(filters=filter_num,\n",
    "                                                    kernel_size=(1, 1),\n",
    "                                                    strides=stride))\n",
    "        downsample.add(tf.keras.layers.BatchNormalization())\n",
    "    else:\n",
    "        downsample = tf.keras.layers.Lambda(lambda x: x)\n",
    "\n",
    "    residual = downsample(x)\n",
    "    x = conv1(x)\n",
    "    x = bn1(x)\n",
    "    x = tf.nn.relu(x)\n",
    "    x = conv2(x)\n",
    "    x = bn2(x)\n",
    "    output = tf.nn.relu(tf.keras.layers.add([residual, x]))\n",
    "    return output\n",
    "\n",
    "def basic_block_layer(x, filter_num, blocks, stride=1):\n",
    "    x = basic_block(x, filter_num, stride=stride)\n",
    "    for _ in range(1, blocks):\n",
    "        x = basic_block(x, filter_num, stride=1)\n",
    "    return x\n",
    "\n",
    "def resnet(x, num_classes, layer_params):\n",
    "    pad1 = tf.keras.layers.ZeroPadding2D(padding=1)\n",
    "    conv1 = tf.keras.layers.Conv2D(filters=64,\n",
    "                                        kernel_size=(3, 3),\n",
    "                                        strides=1,\n",
    "                                        padding=\"same\")\n",
    "    bn1 = tf.keras.layers.BatchNormalization()\n",
    "\n",
    "    avgpool = tf.keras.layers.GlobalAveragePooling2D()\n",
    "    fc = tf.keras.layers.Dense(units=num_classes, activation=tf.keras.activations.softmax)\n",
    "\n",
    "    x = pad1(x)\n",
    "    x = conv1(x)\n",
    "    x = bn1(x)\n",
    "    x = tf.nn.relu(x)\n",
    "    x = basic_block_layer(x, filter_num=64,\n",
    "                                        blocks=layer_params[0])\n",
    "    x = basic_block_layer(x, filter_num=128,\n",
    "                                        blocks=layer_params[1],\n",
    "                                        stride=2)\n",
    "    x = basic_block_layer(x, filter_num=256,\n",
    "                                        blocks=layer_params[2],\n",
    "                                        stride=2)\n",
    "    x = basic_block_layer(x, filter_num=512,\n",
    "                                        blocks=layer_params[3],\n",
    "                                        stride=2)\n",
    "    x = avgpool(x)\n",
    "    output = fc(x)\n",
    "    return output\n",
    "\n",
    "def resnet_18(x, num_classes):\n",
    "    return resnet(x, num_classes, layer_params=[2, 2, 2, 2])\n",
    "\n",
    "def create_model(x_train, y_train, num_classes=10, batch_size=64, epochs=25, callbacks=[]):\n",
    "    inputs = tf.keras.layers.Input(shape=x_train.shape[1:])  # Specify the dimensions\n",
    "    outputs = resnet_18(inputs, num_classes)\n",
    "    model = tf.keras.models.Model(inputs, outputs)\n",
    "\n",
    "    opt = tf.keras.optimizers.SGD(learning_rate=0.1, momentum=0.9, nesterov=True)\n",
    "    model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])\n",
    "\n",
    "    datagen = ImageDataGenerator(\n",
    "        featurewise_center=False,\n",
    "        samplewise_center=False,\n",
    "        featurewise_std_normalization=False,\n",
    "        samplewise_std_normalization=False,\n",
    "        zca_whitening=False,\n",
    "        rotation_range=15,\n",
    "        width_shift_range=0.1,\n",
    "        height_shift_range=0.1,\n",
    "        horizontal_flip=True,\n",
    "        vertical_flip=False\n",
    "        )\n",
    "    \n",
    "    datagen.fit(x_train)\n",
    "    callbacks = callbacks + [TqdmCallback(verbose=0)]\n",
    "    model.fit(datagen.flow(x_train, y_train, batch_size=batch_size), steps_per_epoch=x_train.shape[0] // batch_size,epochs=epochs,verbose=0,callbacks=callbacks)\n",
    "    return model\n",
    "    \n",
    "model_path = \"../../../models/cifar10-resnet18-notebook.h5\"\n",
    "if not os.path.exists(model_path):\n",
    "    model = create_model(x_train, y_train, epochs=80)\n",
    "    model.save(model_path)\n",
    "else:\n",
    "    model = tf.keras.models.load_model(model_path)\n",
    "\n",
    "model.evaluate(x_test, y_test)\n",
    "\n",
    "model_art = TensorFlowV2Classifier(model, nb_classes=10, input_shape=model.input_shape)\n",
    "\n",
    "print(\"Model and data preparation done.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Choose Target Image from Test Set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow.keras.utils import to_categorical\n",
    "\n",
    "# A trigger from class 0 will be classified into class 1.\n",
    "class_source = 0\n",
    "class_target = 1\n",
    "index_target = np.where(y_test.argmax(axis=1)==class_source)[0][5]\n",
    "\n",
    "# Trigger sample\n",
    "x_trigger = x_test[index_target:index_target+1]\n",
    "y_trigger  = to_categorical([class_target], num_classes=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Poison Training Images to Misclassify the Trigger Image\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "8a9b48316b224c689944125fb429983f",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/1 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d735d2c6a4214d81892ef146cf087333",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "0epoch [00:00, ?epoch/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best B-score: 0.46954864\n"
     ]
    }
   ],
   "source": [
    "from art.attacks.poisoning.gradient_matching_attack import GradientMatchingAttack\n",
    "\n",
    "epsilson = 0.01/(std+1e-7)\n",
    "\n",
    "attack = GradientMatchingAttack(model_art,\n",
    "        percent_poison=0.05,\n",
    "        max_trials=1,\n",
    "        max_epochs=500,\n",
    "        clip_values=(min_,max_),\n",
    "        epsilon=epsilson,\n",
    "        verbose=1)\n",
    "\n",
    "x_poison, y_poison = attack.poison(x_trigger, y_trigger, x_train, y_train)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Examples of the trigger, an original sample, and the poisoned sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "plt.imshow(x_trigger[0]*(std+1e-7)+mean)\n",
    "plt.title('Trigger image')\n",
    "plt.show()\n",
    "\n",
    "index_poisoned_example = np.where([np.any(p!=o) for (p,o) in zip(x_poison,x_train)])[0]\n",
    "plt.imshow(x_train[index_poisoned_example[0]]*(std+1e-7)+mean)\n",
    "plt.title('Original image')\n",
    "plt.show()\n",
    "\n",
    "plt.imshow(x_poison[index_poisoned_example[0]]*(std+1e-7)+mean)\n",
    "plt.title('Poisoned image')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training with Poison Images"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These attacks allow adversaries who can poison your dataset the ability to mislabel any particular target instance of their choosing without manipulating labels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "665dfaf852f4488e8ec0697eb8e8639e",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "0epoch [00:00, ?epoch/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.36680835\n",
      "0.07379134\n",
      "0.0035149439\n",
      "0.0017959292\n",
      "0.010571028\n",
      "0.0050093876\n",
      "0.018253107\n",
      "0.004564156\n",
      "0.011471217\n",
      "0.01758528\n",
      "0.00510275\n",
      "0.0013739979\n",
      "0.0059446185\n",
      "0.029887915\n",
      "0.121954076\n",
      "0.03737228\n",
      "0.14674497\n",
      "0.007548481\n",
      "0.37859422\n",
      "0.26576933\n",
      "0.04603827\n",
      "0.0014023243\n",
      "0.34067747\n",
      "0.70433664\n",
      "0.02176013\n",
      "0.022827284\n",
      "0.02348572\n",
      "0.012626419\n",
      "0.086503804\n",
      "0.059962995\n",
      "0.1830254\n",
      "0.009214844\n",
      "0.04208779\n",
      "0.033954155\n",
      "0.04244631\n",
      "0.0056870715\n",
      "0.2157328\n",
      "0.08931625\n",
      "0.27393675\n",
      "0.002363325\n",
      "0.024163112\n",
      "0.00020344515\n",
      "0.24038412\n",
      "0.021390818\n",
      "0.07888789\n",
      "0.088517256\n",
      "0.04684299\n",
      "0.3294824\n",
      "0.06371593\n",
      "0.00014793752\n",
      "0.35774168\n",
      "0.013285882\n",
      "0.28235772\n",
      "0.74389493\n",
      "0.0037503825\n",
      "0.025682572\n",
      "0.9943376\n",
      "0.10753578\n",
      "0.99483454\n",
      "0.06396595\n",
      "0.69573313\n",
      "0.0052862996\n",
      "0.020804293\n",
      "0.006888913\n",
      "0.9936853\n",
      "0.89727944\n",
      "0.6091392\n",
      "0.7845859\n",
      "0.65327674\n",
      "0.058516055\n",
      "0.8614058\n",
      "0.552745\n",
      "0.9157779\n",
      "0.55058527\n",
      "0.019930616\n",
      "0.10405736\n",
      "0.1351475\n",
      "0.34966296\n",
      "0.0012170486\n",
      "0.8807578\n",
      "y_trigger: [[0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]\n",
      "y_: [[4.9007391e-03 8.8075781e-01 1.3130224e-02 7.4657075e-02 1.4029828e-06\n",
      "  3.9072251e-03 3.0878120e-06 1.9337395e-02 3.3348053e-07 3.3046785e-03]]\n",
      "Poisoning was successful.\n"
     ]
    }
   ],
   "source": [
    "class TriggerTestCallback(tf.keras.callbacks.Callback):\n",
    "    def __init__(self, x_trigger, y_trigger):\n",
    "        super().__init__()\n",
    "        self.x_trigger = x_trigger\n",
    "        self.y_trigger = y_trigger\n",
    "\n",
    "    def on_epoch_end(self, epoch, logs=None):\n",
    "        y_ = self.model.predict(x_trigger)\n",
    "        print(y_[0][np.argmax(y_trigger)])\n",
    "        logs[\"Trigger Prediction Score\"] = y_[0][np.argmax(y_trigger)]\n",
    "\n",
    "model_poisoned = create_model(x_poison, y_poison, epochs=80, callbacks=[TriggerTestCallback(x_trigger, y_trigger)])\n",
    "y_ = model_poisoned.predict(x_trigger)\n",
    "\n",
    "print(\"y_trigger:\", y_trigger)\n",
    "print(\"y_:\", y_)\n",
    "\n",
    "if np.argmax(y_trigger) == np.argmax(y_):\n",
    "    print(\"Poisoning was successful.\")\n",
    "else:\n",
    "    print(\"Poisoning failed.\")"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "0efaf3e5c0b4bd1ede177191899ec2ef4ee13bfdededa3ba02bc2fc62340f8fa"
  },
  "kernelspec": {
   "display_name": "Python 3.8.12 64-bit ('art': conda)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
